﻿/*
 * zcmd.cxx
 *
 *  Created on: 2014年10月3日
 *      Author: lvfifi
 */

#include "zpsoe/zcmd.h"
#include "zpsoe/common.h"
#include "zpsoe/zalgorithm/zstring.h"
#include "zpsoe/zlog.h"
#include <cstdlib>
#include <cstdio>

#ifdef PLATFORM_WIN32
    #ifndef INCLUDE_WINDOWS_H_FILE
        #define INCLUDE_WINDOWS_H_FILE
        #include <Windows.h>
    #endif
#endif

using zpsoe::zalgorithm::zstring::trim;
using zpsoe::zalgorithm::zstring::to_str;

namespace zpsoe {

namespace zcmd {

ZPSOE_SHARED_LIB_API bool get_exit_status_of_cmd(const string &cmd) {
    print_log(LOG_TRACE, "cmd=%s%s", OS_LINE_FEED.c_str(), cmd.c_str());

    // 重定向输出到null
    const string redirect_cmd_(cmd + TO_NULL);
    const bool ret_ = (system(redirect_cmd_.c_str()) == 0);

    if (ret_)
        print_log(LOG_TRACE, "ret_=%ssuccessful", OS_LINE_FEED.c_str());
    else
        print_log(LOG_TRACE, "ret_=%sunsuccessful", OS_LINE_FEED.c_str());

    return ret_;
}

ZPSOE_SHARED_LIB_API string get_output_of_cmd(const string &cmd) {
    print_log(LOG_TRACE, "cmd=%s%s", OS_LINE_FEED.c_str(), cmd.c_str());

    int32_t size_ = 2048;
    char buf_[2048];
    string ret_;

    FILE* stream_ = popen(cmd.c_str(), "r");

    if (stream_ != NULL) {
        // 每次从 stream 中读取指定大小的内容
        while (fgets(buf_, size_, stream_))
            ret_ += buf_;

        pclose(stream_);
    }

    trim(ret_);
    print_log(LOG_TRACE, "ret_=%s%s", OS_LINE_FEED.c_str(), ret_.c_str());

    return ret_;
}

#ifdef PLATFORM_WIN32

ZPSOE_SHARED_LIB_API void execute_cmd_with_sub_proc(
        const string &cmd, const uint32_t &delay_secs) {
    print_log(LOG_TRACE, "cmd=%s%s", OS_LINE_FEED.c_str(), cmd.c_str());
    print_log(LOG_TRACE, "delay_secs=%d", delay_secs);

    STARTUPINFO si_;
    PROCESS_INFORMATION pi_;
    ZeroMemory(&si_, sizeof(si_));
    si_.cb = sizeof(si_);
    ZeroMemory(&pi_, sizeof(pi_));

    string cmd_("cmd /c ");

    if (delay_secs > 0)
        cmd_ += "ping 127.0.0.1 -n " + to_str(delay_secs) + " > nul &" + cmd;
    else
        cmd_ += cmd;

    LPSTR lp_str_ = const_cast<LPSTR>(cmd_.c_str());

    BOOL ret_ = ::CreateProcess(
        NULL,     // No module name (use command line)
        lp_str_,  // Command line
        NULL,     // Process handle not inheritable
        NULL,     // Thread handle not inheritable
        FALSE,    // Set handle inheritance to FALSE
        0,        // No creation flags
        NULL,     // Use parent's environment block
        NULL,     // Use parent's starting directory
        &si_,      // Pointer to STARTUPINFO structure
        &pi_);      // Pointer to PROCESS_INFORMATION structure

    if(ret_) {
        // 0 表示立刻返回，不等待线程结束
        WaitForSingleObject(pi_.hProcess, 0);

        // 关闭返回的子进程的进程句柄和主线程句柄
        CloseHandle(pi_.hProcess);
        CloseHandle(pi_.hThread);
    } else
        print_log(LOG_TRACE, "CreateProcess failed (%d).", GetLastError());
}

#endif

} /* namespace zcmd */

} /* namespace zpsoe */
